package rursu.dal.managers;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.client.ClientProtocolException;

import rursu.business.pojo.MovieImage;
import rursu.dal.managers.interfaces.IMovieImageDAL;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.util.Log;

public class MovieImageDALManager implements IMovieImageDAL {

	private static final String LOGGER_TAG = MovieImageDALManager.class.getCanonicalName();
	
	private SQLiteDatabase db;
	
	private static final int ATTEMPT_NUMBER = 5;

	public static final String TABLE_NAME = "movie_images";
	
	protected static final String ROW_ID = "_id";
	protected static final String IMAGE_ID = "image_id";
	protected static final String MOVIE_ID = "movie_id";
	protected static final String SIZE = "size";
	protected static final String TYPE = "type";
	protected static final String URL = "url";
	protected static final String WIDTH = "width";
	protected static final String HEIGHT = "height";
	protected static final String PATH = "path";

	public MovieImageDALManager(SQLiteDatabase db) {
		this.db = db;
	}
	
	public List<MovieImage> get(int movieId) {
		
		return get(movieId, null, null);
	}

	public List<MovieImage> get(int movieId, String size, String type) {

		StringBuilder restriction = new StringBuilder();

		restriction.append(MovieImageDALManager.MOVIE_ID + "="
				+ movieId);

		if (size != null) {
			restriction.append(" AND " + MovieImageDALManager.SIZE + "= \""
					+ size + "\" ");
		}

		if (type != null) {
			restriction.append(" AND " + MovieImageDALManager.TYPE + "= \""
					+ type + "\" ");
		}

		Cursor cursor = db.query(TABLE_NAME, new String[] {
				MovieImageDALManager.TABLE_NAME + "." + MovieImageDALManager.IMAGE_ID,
				MovieImageDALManager.TABLE_NAME + "." + MovieImageDALManager.MOVIE_ID,
				MovieImageDALManager.TABLE_NAME + "." + MovieImageDALManager.SIZE,
				MovieImageDALManager.TABLE_NAME + "." + MovieImageDALManager.TYPE,
				MovieImageDALManager.TABLE_NAME + "." + MovieImageDALManager.URL,
				MovieImageDALManager.TABLE_NAME + "." + MovieImageDALManager.WIDTH,
				MovieImageDALManager.TABLE_NAME + "." + MovieImageDALManager.HEIGHT,
				MovieImageDALManager.TABLE_NAME + "." + MovieImageDALManager.PATH 
				},
				restriction.toString(), null, null, null, null);

		List<MovieImage> movieImages = new ArrayList<MovieImage>();

		cursor.moveToFirst();
		
		
		while ( !cursor.isAfterLast() ) {
			
			MovieImage movieImage = new MovieImage();
			
			movieImage.setId( cursor.getString( cursor.getColumnIndex(MovieImageDALManager.IMAGE_ID) ) );			
			movieImage.setSize( cursor.getString( cursor.getColumnIndex(MovieImageDALManager.SIZE) ) );
			movieImage.setWidth( cursor.getInt( cursor.getColumnIndex(MovieImageDALManager.WIDTH) ) );
			movieImage.setHeight( cursor.getInt( cursor.getColumnIndex(MovieImageDALManager.HEIGHT) ) );
			movieImage.setUrl( cursor.getString( cursor.getColumnIndex(MovieImageDALManager.URL) ) );
			movieImage.setType( cursor.getString( cursor.getColumnIndex(MovieImageDALManager.TYPE) ) );
			movieImage.setMovieId( cursor.getInt( cursor.getColumnIndex(MovieImageDALManager.MOVIE_ID) ) );

			movieImages.add( movieImage );
			
			cursor.moveToNext();
		}

		cursor.close();

		return (movieImages.isEmpty()) ? null : movieImages;		
	}

	public long insert(MovieImage image, int movieId, String path) {
		ContentValues values = new ContentValues();

		values.put(MovieImageDALManager.IMAGE_ID, image.getId());
		values.put(MovieImageDALManager.HEIGHT, image.getHeight());
		values.put(MovieImageDALManager.WIDTH, image.getWidth());
		values.put(MovieImageDALManager.MOVIE_ID, movieId);
		values.put(MovieImageDALManager.PATH, path);
		values.put(MovieImageDALManager.URL, image.getUrl());
		values.put(MovieImageDALManager.SIZE, image.getSize());
		values.put(MovieImageDALManager.TYPE, image.getType());

		return db.insert(TABLE_NAME, null, values);

	}

	public void deleteByImageId(String id) {
		db.delete(TABLE_NAME, MovieImageDALManager.IMAGE_ID + "=" + id, null);
	}

	public void deleteByMovieId(int id) {
		
		//TODO: provide deletion of movies from SD card
		db.delete(TABLE_NAME, MovieImageDALManager.MOVIE_ID + "=" + id, null);
		
	}

	public String getPath(String id, String size, String type) {
		Cursor cursor = db.query(TABLE_NAME, new String[] {				
				MovieImageDALManager.PATH },
				MovieImageDALManager.TYPE + "=\"" + type + "\" AND " +
				MovieImageDALManager.SIZE + "=\"" + size + "\" AND " +
				MovieImageDALManager.IMAGE_ID + "= \"" + id + "\""
				, null, null, null, null);

		String path = null;
		
		cursor.moveToFirst();
		
		if ( !cursor.isAfterLast() ) {
			if ( !cursor.isNull( cursor.getColumnIndex( MovieImageDALManager.PATH ) ) ) {
				path = cursor.getString( cursor.getColumnIndex( MovieImageDALManager.PATH ) );
			}
		}
		
		
		cursor.close();
		return path;
	}

	public void savePath(String id, String path) {
		
		ContentValues values = new ContentValues();

		values.put(MovieImageDALManager.PATH, path);
		
		db.update(TABLE_NAME, values, MovieImageDALManager.IMAGE_ID + "= \"" + id + "\"", null);
	}
	
	public String saveImage(String urlString) {

		Bitmap bitmap = null;
		String filePath = null;
		byte[] imageByteArray = null;
		
		try {
			
			for ( int i=0 ; (bitmap == null) && (i < ATTEMPT_NUMBER); i++ ) {
				
				URL url = new URL( urlString );
				InputStream inputStream = url.openStream();
				
				int bytesNumber = 0;
				while (inputStream.read() != -1) {
					bytesNumber++;
				}
				
				imageByteArray = new byte[bytesNumber];
				
				inputStream = url.openStream();
				
				inputStream.read(imageByteArray);
				
				bitmap = BitmapFactory.decodeByteArray(imageByteArray, 0, imageByteArray.length);
				
				if ( bitmap == null  ) {
					Thread.sleep( 500 );
					continue;
				}				
			}
			
			File path = Environment.getExternalStorageDirectory();
			
			String filename = (new Integer(urlString.hashCode())).toString() + ".png";
			
			File file = new File( path, filename );
			file.createNewFile();
			
			FileOutputStream out = new FileOutputStream(file);
			
			if (imageByteArray != null) {
				out.write(imageByteArray);
				filePath = file.getAbsolutePath();
			} else {
				Log.d(LOGGER_TAG, "bitmap wasn't downloaded successfully");
			}
			
			out.flush();
			out.close();
			
		
		} catch (ClientProtocolException e) {
			
			e.printStackTrace();
		} catch (IOException e) {
			
			e.printStackTrace();
		} catch (InterruptedException e) {

			e.printStackTrace();
		}
		
		return filePath;
	}
	
	public Bitmap getBitmap(String path) {

		Bitmap bitmap = null;
		InputStream inputStream = null;
		
		try {
			
			inputStream = new FileInputStream(path);
			if ( inputStream != null ) {				
				byte[] data = new byte[inputStream.available()];
				
				inputStream.read(data);
				bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
			}
			
		} catch (FileNotFoundException e) {
			
			e.printStackTrace();
			
		} catch (IOException e) {

			e.printStackTrace();
		} finally {
			
			if ( inputStream != null ) {
				try {
					
					inputStream.close();
					
				} catch (IOException e) {
					
					e.printStackTrace();
				}
			}
		}
		
		
		return bitmap;		
	}

	
}
